#region using directives

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using Client.UIHelper;

#endregion

namespace ClientForms
{
    /// <summary>
    /// The exception form can be launched when an exception is caught.  The form allows the user to
    /// view and then submit this information to the server database through the project web service.
    /// </summary>
    public class ExceptionForm : Form
    {
        #region private variables

        private Button cancel;
        private Container components = null;
        private DataStore dataStore;
        private TextBox errorDescription;
        private Label errorReportLabel;
        private string message;
        private string methodname;
        private string source;
        private Serverprocessing sp;
        private string stacktrace;
        private TextBox statusText;
        private Button submit;

        #endregion

        /// <summary>
        /// constructor for the exception submission form
        /// </summary>
        /// <param name="messageIn">The exception message.</param>
        /// <param name="sourceIn">The exception source.</param>
        /// <param name="stackTraceIn">The exception stacktrace.</param>
        /// <param name="methodNameIn">The method that threw the exception.</param>
        public ExceptionForm(string messageIn, string sourceIn, string stackTraceIn, string methodNameIn)
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            message = messageIn;
            source = sourceIn;
            stacktrace = stackTraceIn;
            methodname = methodNameIn;

            string displayText;

            displayText = "Message: " + message + "\r\n\r\n\r\n";
            displayText += "Source: " + source + "\r\n\r\n\r\n";
            displayText += "StackTrace: " + stacktrace + "\r\n\r\n\r\n";
            displayText += "MethodName: " + methodname + "\r\n\r\n\r\n";

            errorDescription.Text = displayText;

            dataStore = new DataStore(this);

            if (dataStore.PaymentSettings == null)
            {
                string dataStoreMessage = "You Cannot use this form until a valid datastore has been received from the web service.";
                MessageBox.Show(dataStoreMessage);
                Close();
                throw new DataStoreAppConfigException(message);
            }
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// Handle the cancel button click.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cancel_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Handle the submit button click.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void submit_Click(object sender, EventArgs e)
        {
            submit.Enabled = false;
            errorDescription.Visible = false;


            statusText.Text = "Your error report is being submitted.  This may take a few moments.";
            Graphics grfx = CreateGraphics();
            SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
            statusText.Width = 350;
            statusText.Height = Convert.ToInt32(sizef.Height) + 50;
            statusText.Location = new Point(170, (Height - statusText.Height)/2);


            var exceptionInfo = new ExceptionInfo(message, source, stacktrace, methodname, dataStore.ProductName, dataStore.Devtoken, dataStore.UniqueMachineID, dataStore.GetLicenseLevel.LicenseLevel, this);

            //initialize the class that handles the web service interaction.
            sp = new Serverprocessing(exceptionInfo);

            //set up the event handlers for processing complete and failed events
            sp.Processingcomplete += new EventHandler<ProcessingCompletedEvent>(ExceptionForm_ProccessingComplete);
            sp.Processingfailed += new EventHandler<ProcessingFailedEvent>(ExceptionForm_ProccessingFailed);

            //proceed with the web service execution
            sp.HandleException();
        }

        /// <summary>
        /// This is a required method to use the server processing class.  This gets called
        /// via an event from server processing to signal the UI that the processing is complete.
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExceptionForm_ProccessingComplete(object sender, ProcessingCompletedEvent e)
        {
            // Map the delegate to the instance method:
            var d = new MarshallThisFuncString(SetExceptionProcessingComplete);
            e.FormReference.Invoke(d, new object[] {e.Message});
        }

        /// <summary>
        /// Set the form to a complete state signifying successful processing.
        /// </summary>
        /// <param name="message"></param>
        private void SetExceptionProcessingComplete(string message)
        {
            statusText.Text = message;
            Graphics grfx = CreateGraphics();
            SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
            statusText.Width = 350;
            statusText.Height = Convert.ToInt32(sizef.Height) + 50;
            statusText.Location = new Point(170, (Height - statusText.Height)/2);

            submit.Enabled = false;
            cancel.Text = "Close";
        }


        /// <summary>
        /// This is a required method to use the server processing class.  Serverprocessing 
        /// communicates with the submit exception web service and notifies the client with
        /// Error message via the ProcessingFailedEventArgs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExceptionForm_ProccessingFailed(object sender, ProcessingFailedEvent e)
        {
            // Map the delegate to the instance method:
            var d = new MarshallThisFuncFailureInfo(SetExceptionProcessingFailed);
            e.FormReference.Invoke(d, new object[] {e.FailureInformation});
        }

        private void SetExceptionProcessingFailed(FailureInfo failureInfo)
        {
            statusText.Text = failureInfo.Message;
            Graphics grfx = CreateGraphics();
            SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
            statusText.Width = 350;
            statusText.Height = Convert.ToInt32(sizef.Height) + 50;
            statusText.Location = new Point(170, (Height - statusText.Height)/2);


            submit.Enabled = false;
            cancel.Text = "Close";

            if (failureInfo.Alert == FailureInfo.AlertType.Port)
            {
                MessageBox.Show("If the web service cannot be reached please " + "verify that the ASP .NET development port matches the port " + "configured in the application web reference and update as " + "necessary.  The application will need to be restarted after " + "the configuration change.");
            }
        }

        private void ExceptionForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (sp != null)
            {
                sp.Cancelprocessing();
            }
        }

        private void ExceptionForm_Load(object sender, EventArgs e)
        {
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.submit = new System.Windows.Forms.Button();
            this.cancel = new System.Windows.Forms.Button();
            this.errorReportLabel = new System.Windows.Forms.Label();
            this.errorDescription = new System.Windows.Forms.TextBox();
            this.statusText = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            // 
            // submit
            // 
            this.submit.AutoSize = true;
            this.submit.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.submit.Location = new System.Drawing.Point(210, 381);
            this.submit.Name = "submit";
            this.submit.Size = new System.Drawing.Size(75, 23);
            this.submit.TabIndex = 3;
            this.submit.Text = "Submit";
            this.submit.Click += new System.EventHandler(this.submit_Click);
            // 
            // cancel
            // 
            this.cancel.AutoSize = true;
            this.cancel.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.cancel.Location = new System.Drawing.Point(426, 381);
            this.cancel.Name = "cancel";
            this.cancel.Size = new System.Drawing.Size(75, 23);
            this.cancel.TabIndex = 4;
            this.cancel.Text = "Cancel";
            this.cancel.Click += new System.EventHandler(this.cancel_Click);
            // 
            // errorReportLabel
            // 
            this.errorReportLabel.AutoSize = true;
            this.errorReportLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.errorReportLabel.Location = new System.Drawing.Point(170, 32);
            this.errorReportLabel.Name = "errorReportLabel";
            this.errorReportLabel.Size = new System.Drawing.Size(89, 16);
            this.errorReportLabel.TabIndex = 6;
            this.errorReportLabel.Text = "Error Report";
            // 
            // errorDescription
            // 
            this.errorDescription.Location = new System.Drawing.Point(172, 153);
            this.errorDescription.Multiline = true;
            this.errorDescription.Name = "errorDescription";
            this.errorDescription.ReadOnly = true;
            this.errorDescription.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.errorDescription.Size = new System.Drawing.Size(364, 209);
            this.errorDescription.TabIndex = 7;
            // 
            // statusText
            // 
            this.statusText.Anchor = System.Windows.Forms.AnchorStyles.None;
            this.statusText.BackColor = System.Drawing.Color.White;
            this.statusText.BorderStyle = System.Windows.Forms.BorderStyle.None;
            this.statusText.Font = new System.Drawing.Font("Tahoma", 8.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.statusText.Location = new System.Drawing.Point(170, 73);
            this.statusText.Multiline = true;
            this.statusText.Name = "statusText";
            this.statusText.ReadOnly = true;
            this.statusText.Size = new System.Drawing.Size(361, 48);
            this.statusText.TabStop = false;
            this.statusText.Text = "This application has experienced a problem.  If you would like to submit this inf" + "ormation directly to the application developer please click the submit button be" + "low.";
            // 
            // ExceptionForm
            // 
            this.BackColor = System.Drawing.Color.White;
            this.BackgroundImage = ClientForms.Resource.error_report;
            this.ClientSize = new System.Drawing.Size(570, 416);
            this.Controls.Add(this.statusText);
            this.Controls.Add(this.errorDescription);
            this.Controls.Add(this.errorReportLabel);
            this.Controls.Add(this.cancel);
            this.Controls.Add(this.submit);
            this.Name = "ExceptionForm";
            this.ShowInTaskbar = false;
            this.Text = "ExceptionForm";
            this.Load += new System.EventHandler(this.ExceptionForm_Load);
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ExceptionForm_FormClosing);
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        #endregion
    }
}